package domain;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.StaleObjectStateException;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class DAOContact extends HibernateDaoSupport implements IDAOContact{

	/**
	 * Rajoute un contact dans la base de donnees.
	 * @param firstname
	 * @param lastname
	 * @param email
	 * @return renvoit le nouveau contact
	 */
	public Contact addContact( String firstname, String lastname, String email){

		Contact contact = new Contact();
		contact.setFirstName(firstname);
		contact.setLastName(lastname);
		contact.setEmail(email);

		/*Session session = null;
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		session = sessionFactory.openSession();
		Transaction tx = session.beginTransaction();
		session.save(contact);
		tx.commit();*/

		getHibernateTemplate().save(contact);
		return contact;
	}

	public Contact addContact(Contact contact){
		getHibernateTemplate().save(contact);
		return contact;
	}

	public Contact addContact(final String firstname, final String lastname, final String email,
			final String zip, final String city,final String country, final String street,
		 final String phoneKind,final String phoneNumber, final ArrayList<Long> groupIds, final String numSiret){
		return (Contact)getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session session) throws
			HibernateException{

				Contact contact;
				if(numSiret == null){
					contact = new Contact(firstname, lastname, email);
				}
				else
				{
					contact = new Entreprise(firstname, lastname, email, Integer.parseInt(numSiret));
				}

				Address adress = new Address(street, city, zip, country);

				PhoneNumber phone = new PhoneNumber(phoneKind, phoneNumber);

				/*Session session = HibernateUtil.getSessionFactory().openSession();
			Transaction tx = session.beginTransaction();*/


				contact.setAdd(adress);
				//contactGroup = (ContactGroup) session.get(ContactGroup.class, contactGroup.getGroupId());
				for(long groupId : groupIds){
					ContactGroup contactGroup = (ContactGroup) session.get(ContactGroup.class, groupId);
					if (contactGroup != null){
						contact.addGroup(contactGroup);
						session.saveOrUpdate(contactGroup);
					}
				}
				contact.addPhone(phone);

				session.save(contact);
				/*tx.commit();
				session.close();*/


				return contact;
			}

		});
	}

	/**
	 * Suppresion d'un contact a partir de son identifiant
	 * @param id
	 * @return vrai si la suppression a bien ete effectuee
	 */
	public boolean deleteContact(final long id){
		return (Boolean)getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session session) throws
			HibernateException{
				boolean success=false;
				/*Session session = HibernateUtil.getSessionFactory().openSession();
				Transaction tx = session.beginTransaction();*/
				Contact contact = (Contact) session.get(Contact.class, id);
				for (Object groupObj : contact.getGroups().toArray()){
					ContactGroup group = (ContactGroup)groupObj;
					group.getContacts().size();
					group.removeContact(contact);
				}

				session.delete(contact);
				/*tx.commit();
				session.close();*/
				success = true;

				return success;
			}
		});
	}

	/**
	 * Recuperation d'un contact a partir de son identifiant
	 * @param id
	 * @return
	 */
	public Contact getContact(final long id){
		return (Contact)getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session session) throws
			HibernateException{
				Contact contact;
				//Session session = HibernateUtil.getSessionFactory().openSession();
				Object contactObject = session.get(Contact.class, id);
				if (contactObject instanceof Contact) {
					contact = (Contact)  contactObject ;
				} else {
					contact = (Entreprise) contactObject ;
				}
				//session.close();
				return contact;
			}
		});
	}
	
	public ArrayList<Contact> getAllContacts() {
		
		final ArrayList<Contact> contacts = new ArrayList<Contact>();
		getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session sessionHibernate) throws
			HibernateException{
				
				Query requete = sessionHibernate.createQuery("select contact from Contact contact").setCacheable(true);
				List<?> list =  requete.list();
				for ( Object obj : list){
					contacts.add((Contact)obj);
				}
				return contacts;
			}
		});	
		
		return contacts;
	}

	public boolean modifyContact(long id, String firstname, String lastname, String email) {
		Contact contact;
		boolean success = false;
		/*Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction tx = session.beginTransaction();
		contact = (Contact) session.get(Contact.class, id);*/
		contact = (Contact) getHibernateTemplate().get(Contact.class, id);
		contact.setFirstName(firstname);
		contact.setLastName(lastname);
		contact.setEmail(email);
		/*tx.commit();
		session.close();*/
		return success;
	}

	/**
	 * Methode qui modifie les coordonees d'un contact
	 * @param id
	 * @param firstname
	 * @param lastname
	 * @param email
	 * @return
	 * 
	 */
	public boolean modifyContact(final long id,final String firstname, final String lastname, final String email,
			final String zip, final String city,final String country, final String street,
			final ArrayList<Long> groupIds, final String numSiret, final int version){
		return (Boolean)getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session sessionHibernate) throws
			HibernateException{
				Contact contact;
				if(numSiret == null){
					contact = (Contact) sessionHibernate.get(Contact.class, id);
				}
				else
				{
					contact = (Contact) sessionHibernate.get(Contact.class, id);
					((Entreprise)contact).setNumSiret(Integer.valueOf(numSiret));

				}
				//contact.setVersion(version);
				contact.setFirstName(firstname);
				contact.setLastName(lastname);
				contact.setEmail(email);

				Address address = contact.getAdd();
				address.setCity(city);
				address.setCountry(country);
				address.setZip(zip);
				address.setStreet(street);
				sessionHibernate.update(address);
				/*Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction tx = session.beginTransaction();*/

				for (Object group : contact.getGroups().toArray()){
					contact.removeGroup((ContactGroup)group);
				}
				
				for(long groupId : groupIds){
					ContactGroup contactGroup = (ContactGroup) sessionHibernate.get(ContactGroup.class, groupId);
					if (contactGroup != null){
						contact.addGroup(contactGroup);
						sessionHibernate.saveOrUpdate(contactGroup);
					}
				}


				//session.saveOrUpdate(contactGroup);
				try {
					if( contact.getVersion() == version) {
						sessionHibernate.update(contact);
					}
					else {
						throw new StaleObjectStateException("Contact", id);
					}
					
				} catch(StaleObjectStateException e) {
					System.out.println("modification impossible");
					return false;
				}
				//getHibernateTemplate().persist(contactGroup);
				/*session.save(contact);
				tx.commit();
				session.close();*/


				return true;
			}
		});
	}

	/**
	 * Renvoit la liste des contacts correspondant au prenom firrstname
	 * @param firstname
	 * @return
	 */
	public ArrayList<Contact> getContactByFirstName(final String firstname){

		final ArrayList<Contact> contacts = new ArrayList<Contact>();
		getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session sessionHibernate) throws
			HibernateException{
				/*Session session = HibernateUtil.getSessionFactory().openSession();
				Query requete = session.createQuery("select contact from Contact contact where contact.firstName = '" + firstname + "'");
				List<?> list =  requete.list();*/
				Query requete = sessionHibernate.createQuery("select contact from Contact contact where contact.firstName = '" + firstname + "'").setCacheable(true);
				List<?> list =  requete.list();
				for ( Object obj : list){
					contacts.add((Contact)obj);
				}
				return contacts;
			}
		});
		//session.close();
		return contacts;
	}


	/**
	 * Renvoit la liste des contacts correspondant au nom lastname
	 * @param lastname
	 * @return
	 */
	public ArrayList<Contact> getContactByLastName(final String lastname){

		final ArrayList<Contact> contacts = new ArrayList<Contact>();
		/*Session session = HibernateUtil.getSessionFactory().openSession();
		List<?> list = session.createCriteria(Contact.class)
				.add(Restrictions.like("lastName", lastname) ).list();*/
		getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session sessionHibernate) throws
			HibernateException{
				Contact contactExample = new Contact();
				contactExample.setLastName(lastname);
//				Query requete = sessionHibernate.createQuery("select contact from Contact contact where contact.lastName = '" + lastname + "'").setCacheable(true);
				Criteria criteria = sessionHibernate.createCriteria(Contact.class).add(Example.create(contactExample));
				List<?> list =  criteria.list();
				for ( Object obj : list){
					contacts.add((Contact)obj);
				}
				return contacts;
			}
		});
		//session.close();
		return contacts;
	}

	/**
	 * Renvoit la liste des contacts correspondant a l'email email
	 * @param email
	 * @return
	 */
	public ArrayList<Contact> getContactByEmail(final String email){
		final ArrayList<Contact> contacts = new ArrayList<Contact>();
		/*Session session = HibernateUtil.getSessionFactory().openSession();
		List<?> list = session.createCriteria(Contact.class)
				.add(Restrictions.like("lastName", lastname) ).list();*/
		getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session sessionHibernate) throws
			HibernateException{
			Criteria requete = sessionHibernate.createCriteria(Contact.class)
						.add(Restrictions.like("email", email) ).setCacheable(true);
				List<?> list =  requete.list();
				for ( Object obj : list){
					contacts.add((Contact)obj);
				}
				return contacts;
			}
		});
		//session.close();
		return contacts;
	}

}
